home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / prntutil / mlist / mlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-25  |  20.4 KB  |  594 lines

  1. /**********************************************************************
  2. **
  3. ** MList [/t tabsize] [/b linebias] fname [fname [...]]
  4. **
  5. ** Create a numbered listing with intelligent line wrap, titles and
  6. ** pagination
  7. **
  8. **  Author : Dan Rhea
  9. **    Date : 07/07/88
  10. ** History : 07/07/88 v1.00 - Started coding
  11. **           07/17/88 v1.01 - Added the /t option
  12. **                            Bumped buffer size up to 255
  13. **                            Added code to finish of a partial page
  14. **           07/13/88 v1.02 - Added full title and footer centering
  15. **           07/28/88 v1.03 - Added error tab check and set default tab
  16. **                            to 8
  17. **                            Fixed starting line of first page
  18. **           08/03/88 v1.04 - Fixed header and footer positions
  19. **                            Added a blank line after the header and
  20. **                            before the footer so entire listing is
  21. **                            visible if it is kept in a binder
  22. **                            Added total lines printed
  23. **           08/22/88 v1.05 - Added code to finish off partial lines
  24. **                            when EOF is hit (i.e. last line ends in
  25. **                            EOF not a newline)
  26. **           08/29/88 v1.06 - By request... a warm fuzzy every 100
  27. **                            lines Added a screen centering routine
  28. **                            Some general output cleanup...
  29. **                            Center all the normal screen output...
  30. **           09/01/88 v1.07 - The ATARI version! (conditional code
  31. **                            included)
  32. **           09/04/88 v1.08 - Minor changes to make the source file
  33. **                            compile and link in either environment
  34. **                            without changes
  35. **           11/07/88 v1.09 - Re-sized page length to work well with a
  36. **                            typical laser printer.
  37. **           11/10/88 v1.10 - Re-worked the centering routines to
  38. **                            reduce a lot of redundant code/routines.
  39. **           03/29/89 v1.11 - Added a line number bias option [/b n]
  40. **           05/01/89 v1.12 - Changed tab logic to use modulis
  41. **                            calculation
  42. **           05/09/89 v1.13 - Added an inhibit line number option [/l]
  43. **           08/26/89 v1.14 - Corrected count error caused by bias
  44. **           11/24/89 v1.15 - Corrections to get Atari version in sync
  45. **
  46. ** Microsoft C 5.1 Compile and link directive (MS-DOS Version)
  47. **
  48. **    CL /AL /Ox \MSC\SRC\MLIST.C \MSC\LIB\SETARGV.OBJ /link /NOE
  49. **
  50. ** Mark Williams C 2.0 CC Directive (Atari GEMDOS Version)
  51. **
  52. **    CC -v MLIST.C
  53. **
  54. ** Copyright (c) 1988 by Dan Rhea, All rights reserved
  55. **                    program may be copied freely,
  56. **                    but never sold or rented
  57. **
  58. **********************************************************************/
  59.  
  60. #include "stdio.h"
  61. #if GEMDOS
  62. #include "osbind.h"
  63. #else
  64. #include "string.h"
  65. #include "malloc.h"
  66. #endif
  67.  
  68. #define  FALSE 0
  69. #define  TRUE  1
  70. #define  WIDTH 80
  71. #define  TAB   0x09
  72. #define  BLANK 0x20
  73. #define  BSIZE 255
  74. #define  PAGELEN  57
  75.  
  76. int   ch;                     /* Character in process */
  77. int   cntr;                   /* Tab expansion counter */
  78. int   last_char;              /* Last character processed */
  79. int   tab_set;                /* Tab expansion value */
  80. unsigned int   ocount;        /* Output buffer line counter */
  81.  
  82. main (argc, argv)
  83. int  argc;
  84. char **argv;
  85. {
  86.  
  87.    /* Define a bunch of stuff... */
  88.    FILE  *fin;                /* File input stream */
  89. #if GEMDOS
  90.    FILE  *stdprn;             /* Printer stream */
  91. #endif
  92.    unsigned char  *lineout;   /* Text output buffer */
  93.    unsigned char  *title;     /* Title buffer */
  94.    unsigned char  *footer;    /* Footer buffer */
  95.    unsigned char  *junk;      /* Scratch buffer */
  96.    unsigned char  *to_screen; /* Screen line buffer */
  97.    unsigned char  *lptr;      /* Text buffer pointer */
  98.    unsigned char  *sptr;      /* Screen buffer pointer */
  99.    unsigned int   c;          /* Current character */
  100.    unsigned int   i;          /* Loop index */
  101.    unsigned int   wrap;       /* Line wrap flag */
  102.    unsigned int   lcount;     /* Output line counter (for display) */
  103.    unsigned int   pcount;     /* Page counter (for display) */
  104.    unsigned int   ccount;     /* Character counter (internal) */
  105.    unsigned int   tcount;     /* Real line counter (internal) */
  106.    unsigned int   acount;     /* All lines printed counter */
  107.    unsigned int   xcount;     /* Adjusted counter */
  108.    unsigned int   pad;        /* Lines to pad out last page */
  109.    unsigned int   tof;        /* Top of form flag */
  110.    unsigned int   first1;     /* First file flag */
  111.    unsigned int   fuzzy;      /* Warm fuzzy variable */
  112.    unsigned int   l_bias;     /* Line counter bias (usually 1) */
  113.    unsigned int   l_num;      /* Line number flag F=Inhibit */
  114.    unsigned int   l_wid;      /* Text line width (71 or 80) */
  115.  
  116.    /* Allocate buffers */
  117.    lineout = (unsigned char *) malloc(BSIZE * sizeof(unsigned char));
  118.    title = (unsigned char *) malloc(BSIZE * sizeof(unsigned char));
  119.    footer = (unsigned char *) malloc(BSIZE * sizeof(unsigned char));
  120.    junk = (unsigned char *) malloc(BSIZE * sizeof(unsigned char));
  121.    to_screen = (unsigned char *) malloc(WIDTH * sizeof(unsigned char));
  122.  
  123. #if GEMDOS
  124.  
  125.    /* Open the printer */
  126.    printf ("\033E");
  127.    if ((stdprn = fopen ("PRN:","w")) == NULL) {
  128.       center_scr ("\007Error: Unable to open printer.", TRUE);
  129.       go_away(1);
  130.    }
  131. #endif
  132.  
  133.    /* Init stuff */
  134.    last_char   = BLANK;
  135.    ch          = BLANK;
  136.    cntr        = FALSE;
  137.    tab_set     = 8;
  138.    lptr        = lineout;
  139.    sptr        = to_screen;
  140.    first1      = TRUE;
  141.    acount      = 0;
  142.    l_bias      = 1;
  143.    l_num       = TRUE;
  144.    l_wid       = 71;
  145.    printf ("\n");
  146.  
  147.    /* Greetings earth person... */
  148.    center_scr ("MLIST v1.15 (c) Copyright 1988, 1989 by Dan Rhea,",
  149.               WIDTH, TRUE);
  150.    center_scr ("All rights reserved.",
  151.               WIDTH, TRUE);
  152.    center_scr (" ",
  153.               WIDTH, TRUE);
  154. #ifndef GEMDOS
  155.    center_scr ("Provided courtesy of DATA BASE Computers and Software",
  156.               WIDTH, TRUE);
  157.    center_scr ("Plantation, FL (305)474-3355",
  158.               WIDTH, TRUE);
  159.    center_scr (" ",
  160.               WIDTH, TRUE);
  161. #endif
  162.    center_scr ("This program can be freely copied but not sold.",
  163.               WIDTH, TRUE);
  164.    center_scr (" ",
  165.               WIDTH, TRUE);
  166.  
  167.    /* Make sure we've got something to do */
  168.    if (argc <= 1) {
  169. #if GEMDOS
  170.       printf ("\007");
  171.       center_scr ("usage: MLIST [-t tab] [-b bias] [-l] file [file [...]]", WIDTH, TRUE);
  172. #else
  173.       printf ("\007");
  174.       center_scr ("usage: MLIST [/t tab] [/b bias] [/l] file [file [...]]", WIDTH, TRUE);
  175. #endif
  176.       center_scr (" ", WIDTH, TRUE);
  177.       center_scr ("/t   = Tab stop change option.                              ", WIDTH, TRUE);
  178.       center_scr ("/b   = Bias line number option.                             ", WIDTH, TRUE);
  179.       center_scr ("/l   = Inhibit line numbers option.                         ", WIDTH, TRUE);
  180.       center_scr ("tab  = Tab expansion of 2 to 255 (defaults to 8).           ", WIDTH, TRUE);
  181.       center_scr ("bias = Value added to line counter (defaults to 1). This is ", WIDTH, TRUE);
  182.       center_scr ("       most usefull for printing file fragments.            ", WIDTH, TRUE);
  183.       center_scr ("file = Full path name of files to print (supports wildcards)", WIDTH, TRUE);
  184.       go_away(1);
  185.    }
  186.  
  187.    /* Loop once for each file supplied via the command line */
  188.    while (--argc > 0) {
  189.        
  190.       /* Open file and handle an error if need be */
  191.       if ((fin = fopen (*++argv, "r")) == NULL) {
  192.  
  193.          /* If the file open falied, see if this is an option */
  194.          if ((*argv)[0] == '-'|| (*argv)[0] == '/') {
  195.  
  196.             /* See if it's a tab option */
  197.             if ((*argv)[1] == 'T' || (*argv)[1] == 't') {
  198.                tab_set = atoi (*++argv);
  199.                argc--;
  200.                if (tab_set < 2 || tab_set > 255) {
  201.                   sprintf (sptr, "\007Error: Tab out of range (2-255), ");
  202.                   center_scr (sptr, WIDTH, TRUE);
  203.                   sptr = to_screen;
  204.                   sprintf (sptr, "forced to tab of 8.");
  205.                   center_scr (sptr, WIDTH, TRUE);
  206.                   sptr = to_screen;
  207.                   tab_set = 8;
  208.                }
  209.             } else {
  210.  
  211.                /* See if it's a line bias option */
  212.                if ((*argv)[1] == 'B' || (*argv)[1] == 'b') {
  213.                   l_bias = atoi (*++argv);
  214.                   argc--;
  215.                   if ((l_bias < 1) || (l_bias > 9999999L)) {
  216.                      sprintf (sptr, "\007Error: Line bias out of range (1-9999999), ");
  217.                      center_scr (sptr, WIDTH, TRUE);
  218.                      sptr = to_screen;
  219.                      sprintf (sptr, "forced to default of 1.");
  220.                      center_scr (sptr, WIDTH, TRUE);
  221.                      sptr = to_screen;
  222.                      l_bias = 1;
  223.                   }
  224.                } else {
  225.  
  226.                   /* See if we have a line number inhibit */
  227.                   if (((*argv)[1] == 'L') || ((*argv)[1] == 'l')) {
  228.                      l_num = FALSE;
  229.                      l_wid = 80;
  230.                   } else {
  231.  
  232.                      /* Option? I don know dis stenkin option... */
  233.                      sprintf (sptr, "\007Error: Invalid command line argument.");
  234.                      center_scr (sptr, WIDTH, TRUE);
  235.                      sptr = to_screen;
  236.  
  237.                   }
  238.                }
  239.             }
  240.          } else {
  241.  
  242.             /* No it's just your plain old everyday non-existant file */
  243.             sprintf (sptr, "\007Error: Unable to open %s.", *argv);
  244.             center_scr (sptr, WIDTH, TRUE);
  245.             sptr = to_screen;
  246.          }
  247.  
  248.       } else {
  249.  
  250.          /* Initialize things since we have a new file to do */
  251.          ccount = tcount = ocount = 0;
  252.          pcount = 1;
  253.          lcount = l_bias;
  254.          sptr = to_screen;
  255.          if (l_num == TRUE) {
  256.             l_wid = 71;
  257.          } else {
  258.             l_wid = 79;
  259.          }
  260.  
  261.          /* Let the world know of our dirty deeds */
  262.          sprintf (sptr, "Printing %s", *argv);
  263.          center_scr (sptr, WIDTH, FALSE);
  264.          sptr = to_screen;
  265.          
  266.          /* Print a title on the listing */
  267.          strcpy (title, "File : ");
  268.          sprintf (junk, "%s", *argv);
  269.          strcat (title, junk);
  270.          tcount = 5;
  271.          if (first1) {
  272.             fprintf (stdprn, "\n\n");
  273.          } else {
  274.             fprintf (stdprn, "\n");
  275.          }
  276.          center_prn (stdprn, title, WIDTH, TRUE);
  277.          if (first1) {
  278.             fprintf (stdprn, "\n\n");
  279.             first1 = FALSE;
  280.          } else {
  281.             fprintf (stdprn, "\n\n");
  282.          }
  283.  
  284.          /* Initialize text buffer for output */
  285.          lptr = lineout;
  286.          for (i = 0; i <= BSIZE; i++) {
  287.             *lptr = BLANK;
  288.             lptr++;
  289.          }
  290.          lcount = l_bias;
  291.          lptr = lineout;
  292.  
  293.          /* Start grabbing data from the input file */
  294.          wrap = FALSE;
  295.          c = get_stuff (fin);
  296.          while (c != EOF) {
  297.             ccount = ccount + 1;
  298.  
  299.             /* Output the line if we get a newline */
  300.             if (c == '\n') {
  301.  
  302.                /* Process a wrapped line */
  303.                if (ocount > l_wid && wrap == TRUE) {
  304.                   if (l_num == TRUE) {
  305.                      fprintf (stdprn, "------> %-72.72s\n", lineout);
  306.                   } else {
  307.                      fprintf (stdprn, "%-80.80s\n", lineout);
  308.                   }
  309.                } else {
  310.  
  311.                   /* Otherwise show a normal numbered one */
  312.                   if (l_num == TRUE) {
  313.                      fprintf (stdprn, "%7d %-72.72s\n", lcount, lineout);
  314.                   } else {
  315.                      fprintf (stdprn, "%-80.80s\n", lineout);
  316.                   }
  317.                }
  318.  
  319.                /* Set things up for the next line */
  320.                wrap = FALSE;
  321.                ccount = ocount = 0;
  322.                fflush (stdprn);
  323.                lptr = lineout;
  324.                for (i = 0; i <= BSIZE; i++) {
  325.                   *lptr = BLANK;
  326.                   lptr++;
  327.                }
  328.                lptr = lineout;
  329.                tcount++;
  330.                lcount++;
  331.  
  332.                /* Put a warm fuzzy on the screen every 10 lines */
  333.                if (l_bias == 1) {
  334.                   xcount = lcount;
  335.                } else {
  336.                   xcount = lcount - l_bias;
  337.                }
  338.                if (l_bias == 1) {
  339.                   fuzzy = lcount / 10;
  340.                } else {
  341.                   fuzzy = (lcount - l_bias) / 10;
  342.                }
  343.                if ((fuzzy * 10) == xcount) {
  344.                   sprintf (sptr, "Printing %s. %d lines so far.", *argv, xcount);
  345.                   center_scr (sptr, WIDTH, FALSE);
  346.                   sptr = to_screen;
  347.                }
  348.             } else {
  349.  
  350.                /* Do a clean line wrap if the line get's too long */
  351.                if (ocount > l_wid && wrap == FALSE) {
  352.                   wrap = TRUE;
  353.                   if (l_num == TRUE) {
  354.                      fprintf (stdprn, "%7d %-72.72s\n", lcount, lineout);
  355.                   } else {
  356.                      fprintf (stdprn, "%-80.80s\n", lineout);
  357.                   }
  358.                   tcount++;
  359.  
  360.                   /* Start the next line to be output */
  361.                   lptr = lineout;
  362.                   for (i = 0; i <= BSIZE; i++) {
  363.                      *lptr = BLANK;
  364.                      lptr++;
  365.                   }
  366.                   lptr = lineout;
  367.                   ccount = 0;
  368.                   *lptr = c;
  369.                   lptr++;
  370.                   ocount++;
  371.                } else {
  372.  
  373.                   /* Otherwise just put the character into the output
  374.                   ** buffer */
  375.                   *lptr = c;
  376.                   lptr++;
  377.                   ocount++;
  378.                }
  379.             }
  380.  
  381.             /* If end of page do footer and advance a page */
  382.             if (tcount >= PAGELEN) {
  383.                strcpy (footer, " \0");
  384.                strcpy (footer, "Page : ");
  385.                strcpy (junk, " \0");
  386.                sprintf (junk, "%5d\014", pcount);
  387.                strcat (footer, junk);
  388.                fprintf (stdprn, "\n\n");
  389.                center_prn (stdprn, footer, WIDTH, FALSE);
  390.                tcount = 0;
  391.                tof = TRUE;
  392.             }
  393.  
  394.             /* Grab another character */
  395.             c = get_stuff (fin);
  396.  
  397.             /* Do a top of form if needed and not EOF */
  398.             if (tof == TRUE && c != EOF) {
  399.                pcount++;
  400.                tcount = 5;
  401.                fprintf (stdprn, "\n");
  402.                center_prn (stdprn, title, WIDTH, TRUE);
  403.                fprintf (stdprn, "\n\n");
  404.                tof = FALSE;
  405.             }
  406.          }
  407.  
  408.          /* Finish off any partial line that may be left over */
  409.          if (ccount > 0) {
  410.             if (wrap == TRUE) {
  411.                if (l_num == TRUE) {
  412.                   fprintf (stdprn, "------> %-72.72s\n", lineout);
  413.                } else {
  414.                   fprintf (stdprn, "%-80.80s\n", lineout);
  415.                }
  416.                wrap = FALSE;
  417.             } else {
  418.                if (l_num == TRUE) {
  419.                   fprintf (stdprn, "%7d %-72.72s\n", lcount, lineout);
  420.                } else {
  421.                   fprintf (stdprn, "%-80.80s\n", lineout);
  422.                }
  423.             }
  424.             fflush (stdprn);
  425.             tcount++;
  426.             lcount++;
  427.          }
  428.  
  429.          /* Finish the page and force a form feed between files */
  430.          lcount--;
  431.          if (l_bias == 1) {
  432.             xcount = lcount;
  433.          } else {
  434.             xcount = lcount - l_bias;
  435.          }
  436.          sprintf (sptr, "Printing %s done, %d lines printed.", *argv, xcount);
  437.          center_scr (sptr, WIDTH, FALSE);
  438.          sptr = to_screen;
  439.          printf ("\n");
  440.          if (l_bias == 1) {
  441.             acount = acount + lcount;
  442.          } else {
  443.             acount = acount + (lcount - l_bias);
  444.          }
  445.          if (tcount != 0) {
  446.  
  447.             /* Purge line buffer if we have a partial line (EOF without
  448.             ** EOL) */
  449.             pad = PAGELEN - tcount;
  450.             for (i = 0; i <= pad; i++) {
  451.                fprintf (stdprn, "\n");
  452.             }
  453.             fprintf (stdprn, "\n");
  454.             strcpy (footer, " \0");
  455.             strcpy (footer, "Page : ");
  456.             strcpy (junk, " \0");
  457.             sprintf (junk, "%5d\014", pcount);
  458.             strcat (footer, junk);
  459.             center_prn (stdprn, footer, WIDTH, FALSE);
  460.             fflush (stdprn);
  461.          }
  462.          fclose (fin);
  463.          l_bias = 1;
  464.       }
  465.    }
  466.  
  467.    /* Say goodnight... */
  468.    printf ("\n");
  469.    sprintf (sptr, "Total lines printed was %d.", acount);
  470.    center_scr (sptr, WIDTH, TRUE);
  471.    sptr = to_screen;
  472.    center_scr ("Done!", WIDTH, TRUE);
  473.    go_away(0);
  474. }
  475.  
  476. /****************************************************************************
  477. ** ret = get_stuff (stream) - Simply reads characters from the file stream
  478. ** and returns it as an integer character. If the tab expansion is on and a
  479. ** tab character is detected it will be expanded with spaces to the requested
  480. ** size
  481. ****************************************************************************/
  482.  
  483. int
  484. get_stuff (st)
  485.  
  486. FILE  *st;  /* Input stream handle */
  487.  
  488.    {
  489.  
  490.    /* See if we are expanding a tab character */
  491.    if (last_char == TAB) {
  492.  
  493.       /* Finish up the expansion if we reach tab size + 1 */
  494.       if ((ocount % tab_set) == 0) {
  495.          ch = getc (st);
  496.          cntr = FALSE;
  497.          last_char = ch;
  498.       } else {
  499.  
  500.          /* Otherwise substitute a blank */
  501.          ch = BLANK;
  502.       }
  503.    } else {
  504.  
  505.       /* If we aren't expanding tabs then simply pass on the
  506.       ** character */
  507.       ch = getc (st);
  508.       last_char = ch;
  509.       cntr = FALSE;
  510.    }
  511.  
  512.    /* See if the current character is a tab, if so start expansion */
  513.    if (ch == TAB) {
  514.       ch = BLANK;
  515.       cntr = TRUE;
  516.    }
  517.  
  518.    /* Return with expansion or a new character */
  519.    return (ch);
  520. }
  521.  
  522. /****************************************************************************
  523. ** center_prn (strm, text, width, flag) - Centers "text" within "width" and
  524. ** sends the result to stdprn. If flag is true end with a \n.
  525. ****************************************************************************/
  526.  
  527. int
  528. center_prn (strm, text, width, flag) 
  529.  
  530. FILE          *strm;
  531. unsigned char *text;
  532. int           width;
  533. int           flag;
  534. {
  535.    int   i;             /* Intermediate input buffer */
  536.    int   to_pad;        /* Padding buffer */
  537.  
  538.    /* Determine the length of "text" and use it to calculate the padding
  539.    ** we need to do, pad the line and output the text */
  540.    to_pad = (width - strlen (text)) / 2;
  541.    for (i = 0; i <= to_pad; i++)
  542.       fprintf (strm, " ");
  543.    fprintf (strm, "%s", text);
  544.    if (flag == TRUE) {
  545.       fprintf (strm, "\n");
  546.    }
  547.    return (0);
  548. }
  549.  
  550. /****************************************************************************
  551. ** center_scr (text, width, flag) - Centers "text" within "width" and sends
  552. ** the result to stdout.
  553. ****************************************************************************/
  554.  
  555. int
  556. center_scr (text, width, flag) 
  557. unsigned char *text;
  558. int           width;
  559. int           flag;
  560. {
  561.    int   i;             /* Intermediate character */
  562.    int   to_pad;        /* Padding buffer */
  563.  
  564.    /* Determine the length of "text" and use it to calculate the
  565.    ** padding we need to do, pad the line and output the text */
  566.    to_pad = (width - strlen (text)) / 2;
  567.    printf ("\r");
  568.    for (i = 0; i <= to_pad; i++)
  569.       printf (" ");
  570.    printf ("%s", text);
  571.    if (flag == TRUE) {
  572.       printf ("\n");
  573.    }
  574.    return (0);
  575. }
  576.  
  577. /****************************************************************************
  578. ** go_away (exitval) - Exit with exitval but if this is Atari GEMDOS then 
  579. **       prompt for a character before returning to shell or desktop
  580. ****************************************************************************/
  581.  
  582. go_away (exitval) 
  583. int exitval;
  584. {
  585.  
  586.    int   c;    /* Scratch input byte */
  587. #if GEMDOS
  588.    center_scr (" ", WIDTH, TRUE);
  589.    center_scr ("Press Return/Enter for the desktop or shell.", WIDTH, TRUE);
  590.    c = getc (stdin);
  591. #endif
  592.    exit (exitval);
  593. }
  594.